﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using System.Collections;
using NHibernate.Criterion;

namespace NHibernateProvider
{
    public class UserRepository : IUserRepository
    {
        private ISessionFactory _sessionFactory;
        public ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                {
                    _sessionFactory = CreateSessionFactory();
                }
                return _sessionFactory;
            }
        }

        public UserRepository()
        {
        }

        private static ISessionFactory CreateSessionFactory()
        {
            Configuration configuration = new Configuration();
            configuration.AddAssembly(Assembly.GetCallingAssembly());
            return configuration.BuildSessionFactory();
        }


        #region IUserRepository Members

        public User GetUserByName(string userName, string appName)
        {
            using (var session = SessionFactory.OpenSession())
            {
                var u = session.CreateCriteria(typeof (User))
                        .Add(Restrictions.Eq("UserName", userName))
                        .Add(Restrictions.Eq("ApplicationName", appName))
                        .UniqueResult() as User;
                return u;
            }
        }

        public void SaveUser(User userToSave)
        {
            using (var session = SessionFactory.OpenSession())
            {
                using (var trans = session.BeginTransaction())
                {
                    session.SaveOrUpdate(userToSave);
                    trans.Commit();
                }
            }
        }

        public void DeleteUser(User userToDelete)
        {
            using (var session = SessionFactory.OpenSession())
            {
                using (var trans = session.BeginTransaction())
                {
                    session.Delete(userToDelete);
                    trans.Commit();
                }
            }
        }

        public List<User> GetAllUsers(int pageIndex, int pageSize, string appName)
        {
            var users = new List<User>();
            using (var session = SessionFactory.OpenSession())
            {
                using (var trans = session.BeginTransaction())
                {
                    users = session.CreateCriteria(typeof(User))
                        .Add(Expression.Eq("ApplicationName", appName))
                        .SetFirstResult(pageIndex * pageSize).SetMaxResults(pageSize)
                        .List<User>() as List<User>;
                }
            }
            return users;
        }

        public int GetNumberOfUsersOnline(DateTime compareTime, string appName)
        {
            using (var session = SessionFactory.OpenSession())
            {
                using (var trans = session.BeginTransaction())
                {
                    IList uList = session.CreateCriteria(typeof(User))
                        .Add(Expression.Eq("ApplicationName", appName))
                        .Add(Expression.Ge("LastActivityDate", compareTime))
                        .List();
                    return uList.Count;
                }
            }
        }

        public User GetUserByID(int userID)
        {
            using (var session = SessionFactory.OpenSession())
            {
                return session.Get<User>(userID);
            }
        }


        public string GetUserNameByEMail(string EMail, string appName)
        {
            using (var session = SessionFactory.OpenSession())
            {
                using (var trans = session.BeginTransaction())
                {
                    IList uList = session.CreateCriteria(typeof(User))
                        .Add(Expression.Eq("EMail", EMail))
                        .Add(Expression.Eq("ApplicationName", appName))
                        .List();
                    if (uList.Count > 0)
                    {
                        User u = (User)uList[0];
                        return u.UserName;
                    }
                    else
                    {
                        return String.Empty;
                    }
                }
            }
        }

        public List<User> FindUsersByEMail(string email, int pageIndex, int pageSize, string appName)
        {
            var users = new List<User>();
            using (var session = SessionFactory.OpenSession())
            {
                using (var trans = session.BeginTransaction())
                {
                    users = session.CreateCriteria(typeof(User))
                        .Add(Expression.Like("EMail", email, MatchMode.Anywhere))
                        .Add(Expression.Eq("ApplicationName", appName))
                        .SetFirstResult(pageIndex * pageSize).SetMaxResults(pageSize)
                        .List<User>() as List<User>;
                }
            }
            return users;
        }

        public List<User> FindUsersByName(string userName, int pageIndex, int pageSize, string appName)
        {
            var users = new List<User>();
            using (var session = SessionFactory.OpenSession())
            {
                using (var trans = session.BeginTransaction())
                {
                    users = session.CreateCriteria(typeof(User))
                        .Add(Expression.Like("UserName", userName, MatchMode.Anywhere))
                        .Add(Expression.Eq("ApplicationName", appName))
                        .SetFirstResult(pageIndex * pageSize).SetMaxResults(pageSize)
                        .List<User>() as List<User>;
                }
            }
            return users;
        }

        #endregion
    }
}
